import React, {useEffect, useMemo, useState} from "react"
import styles from "./RolePage.module.sass"
import {
    addRole,
    authorities,
    Authority,
    authorityTree,
    deleteRole,
    getRoles,
    RoleResponse, updateRoleAuthorities,
    updateRoleName
} from "../../apis/RoleApi";
import {Button, Empty, Form, message, Popconfirm, theme, Tree} from "antd";
import {SUPER_ADMIN_ROLE_NAME} from "../../apis/EmployeeApi";
import SingleInputPopover from "../../components/SingleInputPopover";
import {DeleteOutlined, EditOutlined} from "@ant-design/icons";
import {createUseStyles} from "react-jss";
import {GlobalToken} from "antd/es/theme/interface";
import ArrayUtils from "@zxy-cn/array-utils";
import {observerDashboardPageWrapper} from "../../components/dashboardPages/ObserverDashboardPageWrapper";


export interface pageProps {

}


const useStyles = createUseStyles({
    roleItem: (props: GlobalToken) => ({
        "&:hover": {
            color: props.colorPrimary
        }
    })
})

const RolePage: React.FC<pageProps> = (props) => {

    const [roles, setRoles] = useState<RoleResponse[]>([])
    useEffect(() => {
        getRoles().then(response => {
            setRoles(response.data)
        })
    }, []);
    const displayedRoles = useMemo(() => {
        return roles.filter(it => it.name !== SUPER_ADMIN_ROLE_NAME);
    }, [roles]);

    const [selectedRoleName, setSelectedRoleName] = useState<string>()
    const activatedRole = useMemo(() => {
        return roles.find(it => it.name === selectedRoleName)
    }, [selectedRoleName,roles]);

    const [addRoleForm] = Form.useForm();
    const themeData = theme.useToken();
    let classes = useStyles(themeData.token);

    const [checkedRoleNames, setCheckedRoleNames] = useState<Authority[]>([])
    useEffect(() => {
        if (activatedRole) {
            setCheckedRoleNames(activatedRole.authorities)
        } else {
            setCheckedRoleNames([])
        }
    }, [activatedRole])

    const [loading, setLoading] = useState(false)

    function buildAddRolePopover(button: React.ReactNode) {
        return <SingleInputPopover required onConfirm={async (value) => {
            let response = await addRole(value);
            setRoles(roles.concat({name: value, authorities: [], employeeCount: 0, id: response.data.id}))
        }} title={"添加角色"} fieldName={"角色名称"}>
            {button}
        </SingleInputPopover>
    }
    const [messageApi, contextHolder] = message.useMessage();

    return <>
        {contextHolder}
        <div className={styles.container}>
            <div className={styles.roleContainer}>
                {displayedRoles.length === 0 ?
                    <Empty description={"没有任何自定义角色"}>
                        {buildAddRolePopover(<Button type={"primary"}>立即创建</Button>)}
                    </Empty> : <>
                        {buildAddRolePopover(<Button type={"primary"} block>创建角色</Button>)}
                    </>}
                {displayedRoles.map((role) => <div key={role.name}
                                                   className={[styles.roleItem, classes.roleItem].join(" ")}
                                                   style={{color: selectedRoleName === role.name ? themeData.token.colorPrimary : undefined}}
                >
                    <span onClick={() => {
                        setSelectedRoleName(role.name)
                    }}>{role.name}</span>
                    <div>
                        <Button type={"link"} size={"small"} shape={"circle"}>
                            <SingleInputPopover required fieldName={"角色名称"} onConfirm={async (value) => {
                                await updateRoleName(role.name, value)
                                const index = roles.findIndex(it => it.name === role.name)
                                let array = Array.from(roles);
                                array[index] = {...role, name: value}
                                setRoles(array)
                            }} title={"修改角色"}>
                                <EditOutlined/>
                            </SingleInputPopover>
                        </Button>
                        <Button type={"link"} size={"small"} shape={"circle"} danger>
                            <Popconfirm trigger={"click"}
                                        title={`是否删除?${role.employeeCount ? `（${role.employeeCount}人将移除此权限）` : ""}`}
                                        okText={"是"}
                                        cancelText={"再想想"}
                                        onConfirm={() => {
                                            deleteRole(role.name).then(() => {
                                                const array = Array.from(roles)
                                                ArrayUtils.remove(array, role)
                                                setRoles(array)
                                            })
                                        }}
                            >
                                <DeleteOutlined disabled/>
                            </Popconfirm>
                        </Button>
                    </div>

                </div>)}
            </div>
            {!!activatedRole ? <div className={styles.authorityTreeContainer}>
                <div className={styles.selectedRoleName}>{selectedRoleName}</div>
                <Tree checkedKeys={checkedRoleNames ?? []} treeData={authorityTree}
                      onCheck={(checkedKeys) => {
                          let checkedRoleNames = checkedKeys as Authority[];
                          setCheckedRoleNames(checkedRoleNames.filter(it => authorities.includes(it)))
                      }}
                      defaultExpandAll checkable className={styles.authorityTree}/>
                <Button className={styles.button} type={"primary"} onClick={() => {
                    setLoading(true)
                    updateRoleAuthorities(activatedRole!.name, checkedRoleNames)
                        .then(() => {
                            const array = Array.from(roles)
                            let index = array.indexOf(activatedRole);
                            const role = array[index]
                            array[index] = {
                                ...role,
                                authorities: checkedRoleNames,
                            }
                            setRoles(array)
                            return messageApi.success("保存成功")
                        }).finally(() => {
                        setLoading(false)
                    })
                }} loading={loading}>保存权限</Button>
            </div> : <div className={styles.authorityTreeContainerEmpty}>
                <Empty description={"请先选择角色"}/>
            </div>}
        </div>
    </>
}


export default observerDashboardPageWrapper(RolePage, "roles", "角色")
